package cn.siriusbot.rpc.client.processor;

import cn.siriusbot.rpc.*;
import cn.siriusbot.rpc.entity.RpcBody;
import cn.siriusbot.rpc.entity.RpcError;
import cn.siriusbot.rpc.entity.RpcNativeBody;
import cn.siriusbot.rpc.utils.SerializeUtils;
import cn.siriusbot.siriuspro.error.MsgException;
import cn.siriusbot.siriuspro.web.R.R;
import com.alibaba.fastjson2.JSONObject;
import lombok.SneakyThrows;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.net.MalformedURLException;
import java.net.URL;

public class HttpRpcProcessor implements RpcProcessor, SiriusLoggerTransmit {
    // 创建 HttpClient 实例
    private static final CloseableHttpClient httpClient;

    static {
        // 创建连接池管理器
        PoolingHttpClientConnectionManager connectionManager =
                new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(20);
        httpClient = HttpClientBuilder.create()
                .setConnectionManager(connectionManager)
                .build();
    }


    /**
     * 请求地址
     */
    private final String address;


    @SneakyThrows
    public HttpRpcProcessor(String siriusUrl, String packageName) {
        this.address = String.format("%s/api/plugin/%s/sirius-rpc", formatUrl(siriusUrl), packageName);
    }

    private String formatUrl(String urlString) throws MalformedURLException {
        URL url = new URL(urlString);
        String protocol = url.getProtocol() + "://";
        String host = url.getHost();
        int port = url.getPort();
        if (port != -1) {
            host += ":" + port;
        }
        return protocol + host;
    }


    /**
     * 获取一个处理结果
     *
     * @param context 请求上下文
     * @param body    请求详细
     * @return 返回结果
     */
    @SneakyThrows
    @Override
    public Object getResult(RpcContext context, RpcNativeBody body) {
        final RpcBody rpcBody = context.toJsonRpcBody(body);

        HttpPost post = new HttpPost(this.address);
        post.setHeader("Content-Type", "application/json");
        post.setEntity(new StringEntity(JSONObject.toJSONString(rpcBody)));
        log.info("[HTTP]RPC请求 -> " + this.address + " body -> " + rpcBody);
        final CloseableHttpResponse response = httpClient.execute(post);
        if (response.getStatusLine().getStatusCode() != 200) {
            throw new MsgException(500, "RPC请求错误，HTTP状态码不为200");
        }
        final String responseBody = EntityUtils.toString(response.getEntity());
        final R r = JSONObject.parseObject(responseBody, R.class);
        if (r.getCode() != 0) {
            throw new MsgException(r.getCode(), r.getMsg());
        }
        if (r.getData() instanceof JSONObject) {
            final RpcBody result = ((JSONObject) r.getData()).to(RpcBody.class);
            final RpcError error = result.getError();
            if (error != null) {
                throw new MsgException(500, String.format("RPC服务器抛出异常，异常标记码:%s，异常信息:%s", error.getErrorId(), error.getMessage()));
            }
            // 处理返回结果
            return SerializeUtils.parsecJsonObject(result.getResult(), body.getReturnType());
        }
        throw new MsgException(500, "RPC请求错误，序列化结果异常");
    }

    private SiriusLogger log = new PrintLog();

    @Override
    public SiriusLogger getLog() {
        return log;
    }

    @Override
    public void setLog(SiriusLogger logger) {
        this.log = logger;
    }
}
